package com.lifeverse.controller;

import com.lifeverse.common.ApiResponse;
import com.lifeverse.entity.NetworkHealthMetrics;
import com.lifeverse.service.NetworkAnomalyDetector;
import com.lifeverse.service.NetworkHealthMonitor;
import com.lifeverse.repository.NetworkHealthMetricsRepository;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 网络监控控制器
 */
@Slf4j
@RestController
@RequestMapping("/network/monitoring")
@RequiredArgsConstructor
@Tag(name = "网络监控", description = "网络健康状态监控和异常检测")
public class NetworkMonitoringController {
    
    private final NetworkHealthMonitor networkHealthMonitor;
    private final NetworkAnomalyDetector anomalyDetector;
    private final NetworkHealthMetricsRepository metricsRepository;
    
    @Operation(summary = "获取全局网络健康状态", description = "获取当前全局网络的健康指标")
    @GetMapping("/global/health")
    public ApiResponse<NetworkHealthMetrics> getGlobalNetworkHealth() {
        log.info("获取全局网络健康状态");
        NetworkHealthMetrics metrics = networkHealthMonitor.calculateGlobalNetworkMetrics();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取群体网络健康状态", description = "获取指定群体的网络健康指标")
    @GetMapping("/group/{groupId}/health")
    public ApiResponse<NetworkHealthMetrics> getGroupNetworkHealth(
            @Parameter(description = "群体ID") @PathVariable Long groupId) {
        log.info("获取群体网络健康状态: groupId={}", groupId);
        // 这里需要先获取群体信息，然后计算健康指标
        // 简化实现，返回示例数据
        NetworkHealthMetrics metrics = new NetworkHealthMetrics();
        metrics.setNetworkType(NetworkHealthMetrics.NetworkType.GROUP_BASED);
        metrics.setNetworkIdentifier("GROUP_" + groupId);
        metrics.setOverallHealthScore(BigDecimal.valueOf(75.50));
        metrics.setHealthStatus(NetworkHealthMetrics.HealthStatus.GOOD);
        metrics.setMeasurementTime(LocalDateTime.now());
        
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取最新的网络健康指标", description = "获取最近的网络健康监控数据")
    @GetMapping("/metrics/latest")
    public ApiResponse<List<NetworkHealthMetrics>> getLatestMetrics(
            @Parameter(description = "数量限制") @RequestParam(defaultValue = "10") int limit) {
        List<NetworkHealthMetrics> metrics = metricsRepository.findTop10ByOrderByMeasurementTimeDesc();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "根据网络类型获取健康指标", description = "获取指定网络类型的健康指标")
    @GetMapping("/metrics/type/{networkType}")
    public ApiResponse<Page<NetworkHealthMetrics>> getMetricsByType(
            @Parameter(description = "网络类型") @PathVariable NetworkHealthMetrics.NetworkType networkType,
            @PageableDefault(size = 20) Pageable pageable) {
        Page<NetworkHealthMetrics> metrics = metricsRepository.findByNetworkType(networkType, pageable);
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "根据健康状态获取指标", description = "获取指定健康状态的网络指标")
    @GetMapping("/metrics/status/{healthStatus}")
    public ApiResponse<Page<NetworkHealthMetrics>> getMetricsByHealthStatus(
            @Parameter(description = "健康状态") @PathVariable NetworkHealthMetrics.HealthStatus healthStatus,
            @PageableDefault(size = 20) Pageable pageable) {
        Page<NetworkHealthMetrics> metrics = metricsRepository.findByHealthStatus(healthStatus, pageable);
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取健康的网络", description = "获取所有健康状态良好的网络")
    @GetMapping("/healthy")
    public ApiResponse<List<NetworkHealthMetrics>> getHealthyNetworks() {
        List<NetworkHealthMetrics> metrics = metricsRepository.findHealthyNetworks();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取不健康的网络", description = "获取所有健康状态不佳的网络")
    @GetMapping("/unhealthy")
    public ApiResponse<List<NetworkHealthMetrics>> getUnhealthyNetworks() {
        List<NetworkHealthMetrics> metrics = metricsRepository.findUnhealthyNetworks();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取需要预警的网络", description = "获取所有需要预警的网络")
    @GetMapping("/alerts")
    public ApiResponse<List<NetworkHealthMetrics>> getNetworksNeedingAlert() {
        List<NetworkHealthMetrics> metrics = metricsRepository.findNetworksNeedingAlert();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取有异常的网络", description = "获取所有检测到异常的网络")
    @GetMapping("/anomalies")
    public ApiResponse<List<NetworkHealthMetrics>> getNetworksWithAnomalies() {
        List<NetworkHealthMetrics> metrics = metricsRepository.findNetworksWithAnomalies();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取网络健康趋势", description = "获取指定网络类型的健康评分趋势")
    @GetMapping("/trends/health")
    public ApiResponse<List<Object[]>> getNetworkHealthTrend(
            @Parameter(description = "网络类型") @RequestParam NetworkHealthMetrics.NetworkType networkType,
            @Parameter(description = "天数") @RequestParam(defaultValue = "7") int days) {
        List<Object[]> trend = networkHealthMonitor.getNetworkHealthTrend(networkType, days);
        return ApiResponse.success(trend);
    }
    
    @Operation(summary = "获取网络性能趋势", description = "获取指定网络类型的性能趋势")
    @GetMapping("/trends/performance")
    public ApiResponse<List<Object[]>> getNetworkPerformanceTrend(
            @Parameter(description = "网络类型") @RequestParam NetworkHealthMetrics.NetworkType networkType,
            @Parameter(description = "天数") @RequestParam(defaultValue = "7") int days) {
        List<Object[]> trend = networkHealthMonitor.getNetworkPerformanceTrend(networkType, days);
        return ApiResponse.success(trend);
    }
    
    @Operation(summary = "检测网络异常", description = "对指定网络进行异常检测")
    @PostMapping("/anomaly-detection/{metricsId}")
    public ApiResponse<NetworkAnomalyDetector.AnomalyDetectionResult> detectAnomalies(
            @Parameter(description = "指标ID") @PathVariable Long metricsId) {
        log.info("检测网络异常: metricsId={}", metricsId);
        
        NetworkHealthMetrics metrics = metricsRepository.findById(metricsId)
                .orElseThrow(() -> new RuntimeException("指标不存在: " + metricsId));
        
        NetworkAnomalyDetector.AnomalyDetectionResult result = anomalyDetector.detectAnomalies(metrics);
        return ApiResponse.success(result);
    }
    
    @Operation(summary = "批量检测异常", description = "对所有网络进行批量异常检测")
    @PostMapping("/anomaly-detection/batch")
    public ApiResponse<Map<String, NetworkAnomalyDetector.AnomalyDetectionResult>> batchDetectAnomalies() {
        log.info("批量检测网络异常");
        Map<String, NetworkAnomalyDetector.AnomalyDetectionResult> results = anomalyDetector.batchDetectAnomalies();
        return ApiResponse.success(results);
    }
    
    @Operation(summary = "获取网络统计信息", description = "获取网络监控的统计信息")
    @GetMapping("/statistics")
    public ApiResponse<Map<String, Object>> getNetworkStatistics() {
        Map<String, Object> statistics = new HashMap<>();
        
        // 健康状态分布
        List<Object[]> healthStatusStats = metricsRepository.countByHealthStatus();
        Map<String, Long> healthStatusCount = new HashMap<>();
        for (Object[] stat : healthStatusStats) {
            healthStatusCount.put(stat[0].toString(), (Long) stat[1]);
        }
        statistics.put("healthStatusDistribution", healthStatusCount);
        
        // 网络类型分布
        List<Object[]> networkTypeStats = metricsRepository.countByNetworkType();
        Map<String, Long> networkTypeCount = new HashMap<>();
        for (Object[] stat : networkTypeStats) {
            networkTypeCount.put(stat[0].toString(), (Long) stat[1]);
        }
        statistics.put("networkTypeDistribution", networkTypeCount);
        
        // 平均指标
        LocalDateTime since = LocalDateTime.now().minusDays(7);
        BigDecimal avgHealthScore = metricsRepository.calculateAverageHealthScore(since);
        Double avgResponseTime = metricsRepository.calculateAverageResponseTime(since);
        BigDecimal avgErrorRate = metricsRepository.calculateAverageErrorRate(since);
        BigDecimal avgAvailability = metricsRepository.calculateAverageAvailability(since);
        
        statistics.put("averageHealthScore", avgHealthScore);
        statistics.put("averageResponseTime", avgResponseTime);
        statistics.put("averageErrorRate", avgErrorRate);
        statistics.put("averageAvailability", avgAvailability);
        
        return ApiResponse.success(statistics);
    }
    
    @Operation(summary = "手动触发全局网络监控", description = "手动触发一次全局网络健康监控")
    @PostMapping("/trigger/global")
    public ApiResponse<Void> triggerGlobalMonitoring() {
        log.info("手动触发全局网络监控");
        networkHealthMonitor.monitorGlobalNetworkHealth();
        return ApiResponse.success();
    }
    
    @Operation(summary = "手动触发群体网络监控", description = "手动触发一次群体网络健康监控")
    @PostMapping("/trigger/groups")
    public ApiResponse<Void> triggerGroupMonitoring() {
        log.info("手动触发群体网络监控");
        networkHealthMonitor.monitorGroupNetworkHealth();
        return ApiResponse.success();
    }
    
    @Operation(summary = "获取高连通性网络", description = "获取连通性评分高的网络")
    @GetMapping("/high-connectivity")
    public ApiResponse<List<NetworkHealthMetrics>> getHighConnectivityNetworks() {
        List<NetworkHealthMetrics> metrics = metricsRepository.findHighConnectivityNetworks();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取稳定的网络", description = "获取稳定性评分高的网络")
    @GetMapping("/stable")
    public ApiResponse<List<NetworkHealthMetrics>> getStableNetworks() {
        List<NetworkHealthMetrics> metrics = metricsRepository.findStableNetworks();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取高活跃度网络", description = "获取活跃度评分高的网络")
    @GetMapping("/high-activity")
    public ApiResponse<List<NetworkHealthMetrics>> getHighActivityNetworks() {
        List<NetworkHealthMetrics> metrics = metricsRepository.findHighActivityNetworks();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取高效率网络", description = "获取效率评分高的网络")
    @GetMapping("/high-efficiency")
    public ApiResponse<List<NetworkHealthMetrics>> getHighEfficiencyNetworks() {
        List<NetworkHealthMetrics> metrics = metricsRepository.findHighEfficiencyNetworks();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取创新能力强的网络", description = "获取创新评分高的网络")
    @GetMapping("/innovative")
    public ApiResponse<List<NetworkHealthMetrics>> getInnovativeNetworks() {
        List<NetworkHealthMetrics> metrics = metricsRepository.findInnovativeNetworks();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取大型网络", description = "获取节点数量多的大型网络")
    @GetMapping("/large")
    public ApiResponse<List<NetworkHealthMetrics>> getLargeNetworks(
            @Parameter(description = "最小节点数") @RequestParam(defaultValue = "100") Integer minSize) {
        List<NetworkHealthMetrics> metrics = metricsRepository.findLargeNetworks(minSize);
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取高密度网络", description = "获取网络密度高的网络")
    @GetMapping("/high-density")
    public ApiResponse<List<NetworkHealthMetrics>> getHighDensityNetworks() {
        List<NetworkHealthMetrics> metrics = metricsRepository.findHighDensityNetworks();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取响应快的网络", description = "获取响应时间短的网络")
    @GetMapping("/fast-response")
    public ApiResponse<List<NetworkHealthMetrics>> getFastResponseNetworks(
            @Parameter(description = "最大响应时间(ms)") @RequestParam(defaultValue = "100") Long maxTime) {
        List<NetworkHealthMetrics> metrics = metricsRepository.findFastResponseNetworks(maxTime);
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取低错误率网络", description = "获取错误率低的网络")
    @GetMapping("/low-error")
    public ApiResponse<List<NetworkHealthMetrics>> getLowErrorRateNetworks() {
        List<NetworkHealthMetrics> metrics = metricsRepository.findLowErrorRateNetworks();
        return ApiResponse.success(metrics);
    }
    
    @Operation(summary = "获取高可用性网络", description = "获取可用性高的网络")
    @GetMapping("/high-availability")
    public ApiResponse<List<NetworkHealthMetrics>> getHighAvailabilityNetworks() {
        List<NetworkHealthMetrics> metrics = metricsRepository.findHighAvailabilityNetworks();
        return ApiResponse.success(metrics);
    }
}